import { _decorator, Animation, Collider2D, IPhysics2DContact, Node, Prefab } from 'cc';
import Biz from '../../biz';
import { EntityName } from '../../consts/resources';
import Utils from '../../utils';
import { BulletType, getBulletConfig } from '../config/bullet';
import { getEnemyConfig, RoleConfig } from '../config/enemy';
import { AbstractEntity, generatePos, HpProperty, RoleAnimation } from './common';
import { EventName } from '../../consts/events';
const { ccclass } = _decorator;

@ccclass('Enemy')
export class Enemy extends AbstractEntity {
    private config: RoleConfig;
    private roleAnima = new RoleAnimation();
    public init(name: string) {
        if (this.isInit) return;
        this.isInit = true;
        this.roleName = name;
        this.config = getEnemyConfig(name);
        this.roleAnima.init(Utils.tools.upperFirstLetter(name));
        Utils.events.on(EventName.EndGame, this.onEndGame, this);
    }
    protected destructor(): void {
        Utils.events.off(EventName.EndGame, this.onEndGame, this);
    }
    private onEndGame(): void {
        this.exitTheWorld();
    }

    public joinTheWorld(): void {
        if (this.isJoinTheWorld) return;
        this.colliderBody.enabled = true;
        this.isJoinTheWorld = true;
        this.node.active = true;
        const pos = generatePos(this.size);
        this.node.setPosition(pos.x, pos.y);
        this.hp.init(this.config.hp);
        this.roleAnima.idle(this.anima);
    }
    public exitTheWorld(): void {
        if (!this.isJoinTheWorld) return;
        this.isJoinTheWorld = false;
        this.colliderBody.enabled = false;
        this.node.active = false;
        Utils.pool.returnNode(this.node);
    }

    protected update(dt: number): void {
        if (!Biz.global.isStart || !this.isJoinTheWorld) return;
        if (this.hp.isDead()) return;
        this.node.setPosition(this.node.position.x, this.node.position.y + this.config.speed * dt);
        const area = Utils.sys.getPlatform().windowSize;
        if (this.node.position.y < -area.height) {
            this.exitTheWorld();
        }
    }
    private dead(): void {
        this.colliderBody.enabled = false;
        this.roleAnima.dead(this.anima);
        Utils.audio.playOneShot(`audio/${this.roleName}_down`);
        this.anima.on(Animation.EventType.FINISHED, this.afterDead, this);
    }
    private afterDead(): void {
        this.anima.off(Animation.EventType.FINISHED, this.afterDead, this);
        this.exitTheWorld();
    }
    private hit(): void {
        if (this.hp.isDead()) return;
        this.roleAnima.hit(this.anima);
    }

    // 碰撞检测
    private hp = new HpProperty();
    protected onPhysicsCollision(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
        if (!Utils.sys.isEnterScreen(Utils.tools.toV2(this.node.position), this.size)) {
            return; // 还没进入屏幕
        }
        if (this.hp.isDead()) {
            return;
        }
        if (otherCollider.node.name === EntityName.Player) {
            Biz.hp.subHp(this.config.crashDanger); // 撞到玩家，扣减hp值
            return;
        }
        if (otherCollider.node.name === BulletType.BulletPlayer) {
            const bulletConfig = getBulletConfig(BulletType.BulletPlayer);
            this.hp.sub(bulletConfig.danger);
            if (this.hp.isDead()) {
                Biz.score.addScore(this.config.hp);
                this.dead();
            } else {
                this.hit(); // 只有撞到玩家的子弹就掉血
            }
        }
    }
}

export const createEnemy = (root: Node, prefab: Prefab): Enemy => {
    const body = Utils.pool.createNode(prefab);
    body.setParent(root);
    let entity = body.getComponent(Enemy);
    if (!entity) {
        entity = body.addComponent(Enemy);
        entity.init(prefab.name);
    }
    entity.joinTheWorld();

    return entity;
};
